/**
 * 
 */
package br.usp.icmc.dilvan.aimTemplateViewer.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import name.pehl.totoe.xml.client.Document;
import name.pehl.totoe.xml.client.Node;
import name.pehl.totoe.xml.client.XmlParser;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.AlgorithmTypeAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.AllowedTermAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.AnatomicEntityAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.AnatomicEntityCharacteristicAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.CalculationTypeAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.ComponentAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.ImagingObservationAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.ImagingObservationCharacteristicAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.QuestionTypeAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.TemplateAIMTemplate;
import br.usp.icmc.dilvan.aimTemplateViewer.client.aimTemplate.TemplateContainerAIMTemplate;
 
/**
 * @author dilvan
 *
 */
public class AIMTemplateParser {
	static Map<String, String> aimTemplateFiles= new HashMap<String, String>();
	static Map<String, TemplateAIMTemplate> cache= new HashMap<String, TemplateAIMTemplate>();
		
	static final String NAMESPACE= "xmlns:aim=\"gme://caCORE.caCORE/3.2/edu.northwestern.radiology.AIMTemplate\" "
            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";

	static public void setAIMTemplateContainers(Map<String, String> map) {		
		aimTemplateFiles= map;			
	}
	
	static public List<TemplateContainerAIMTemplate> getTemplateContainers() {
		List<TemplateContainerAIMTemplate> result = new ArrayList<TemplateContainerAIMTemplate>();
		for (String container : aimTemplateFiles.keySet())
			result.add(new TemplateContainerAIMTemplate(container));
		return result;
	}
	
	static public List<TemplateAIMTemplate> getShortTemplates(String container)
			throws IllegalArgumentException {
//		System.out.println("getShortTemplates= " + container);

		List<TemplateAIMTemplate> result = new ArrayList<TemplateAIMTemplate>();
		Document document = new XmlParser().parse(aimTemplateFiles.get(container), NAMESPACE);
		for (Node node : document.selectNodes("//aim:Template"))
			result.add(new TemplateAIMTemplate(
					node.selectValue("@name"),
					node.selectValue("@codeMeaning"),
					node.selectValue("@codeValue")));	
		return result;
	}
		
	static public TemplateAIMTemplate getTemplate(String container, String template) {
		TemplateAIMTemplate result = cache.get(container+template);
		if (result!=null) return result;
//		System.out.println("getTemplate= " + container + " " + template);
		
		//String text= GlobalResources.INSTANCE.vASARITemplatesV1rv233MixedModalities().getText();
		result= parseTemplate(aimTemplateFiles.get(container), template);
		cache.put(container+template, result);
		return result;
	}
	
	static public TemplateAIMTemplate parseTemplate(String content, String template) {
		
		Document document = new XmlParser().parse(content, NAMESPACE);
		
//		System.out.println("valueFirst= " + node.selectValue("@name"));

		TemplateAIMTemplate result= new TemplateAIMTemplate();
		List<Node> templates = document.selectNodes("//aim:Template");
		for (Node node : templates){
			if (node.selectValue("@name").equals(template))
				result = new TemplateAIMTemplate(node.selectValue("@name"), 
						node.selectValue("@codeMeaning"),
						node.selectValue("@codeValue"),
						parseComponentAIMTemplate(node.selectNodes("aim:Component")));
		}
		return result;
	}
	
	// the main class
	static ArrayList<ComponentAIMTemplate> parseComponentAIMTemplate(List<Node> components){
		ArrayList<ComponentAIMTemplate> result = new ArrayList<ComponentAIMTemplate>();
		for (Node c : components){
			result.add(new ComponentAIMTemplate(c.selectValue("@label"),
					Integer.parseInt(c.selectValue("@maxCardinality")),
					Integer.parseInt(c.selectValue("@minCardinality")),
					Integer.parseInt(c.selectValue("@itemNumber")),
					c.selectValue("@shouldDisplay").equalsIgnoreCase("true"),
					parseAllowedTerm(c.selectNodes("aim:AllowedTerm")),
					parseAnatomicEntity(c.selectNode("aim:AnatomicEntity")),
					parseImagingObservation(c.selectNode("aim:ImagingObservation")),
					parseQuestionType(c.selectNode("aim:QuestionType")),
					parseCalculation(c.selectNode("aim:Calculation"))));
		}
		return result;
	}
	
	static ArrayList<AllowedTermAIMTemplate> parseAllowedTerm(List<Node> nodes){
		ArrayList<AllowedTermAIMTemplate> result = new ArrayList<AllowedTermAIMTemplate>();
		for (Node ae: nodes ){
			result.add(new AllowedTermAIMTemplate(ae.selectValue("@codeMeaning"), ae.selectValue("@codeValue")));
		}
		return result;
	}
	
	static AnatomicEntityAIMTemplate parseAnatomicEntity(Node anatomicEntity){
		// we had a problem with null pointer exception in here
		if (anatomicEntity == null)
			return null;
		AnatomicEntityAIMTemplate result = new AnatomicEntityAIMTemplate();
		ArrayList<AnatomicEntityCharacteristicAIMTemplate> anatomicEntityCharacteristicAIMTemplates = new ArrayList<AnatomicEntityCharacteristicAIMTemplate>();
		for (Node aec : anatomicEntity.selectNodes("aim:AnatomicEntityCharacteristic") ){
			anatomicEntityCharacteristicAIMTemplates.add(
					new AnatomicEntityCharacteristicAIMTemplate(
							aec.selectValue("@annotatorConfidence").equalsIgnoreCase("true"), 
							aec.selectValue("@shouldDisplay").equalsIgnoreCase("true"), 
							Integer.parseInt(aec.selectValue("@itemNumber")),
							Integer.parseInt(aec.selectValue("@minCardinality")),
							Integer.parseInt(aec.selectValue("@maxCardinality")),
							aec.selectValue("@label"),
							aec.selectValue("@explanatoryText"),
							parseAllowedTermComponentCharacteristic(aec.selectNodes("aim:AllowedTerm"))));
		}
		result.setAnoAnatomicEntityCharacteristicAIMTemplates(anatomicEntityCharacteristicAIMTemplates);
		result.setAnnotatorConfidence(anatomicEntity.selectValue("@annotatorConfidence").equalsIgnoreCase("true"));
		return result;
	}

	static ArrayList<AllowedTermAIMTemplate> parseAllowedTermComponentCharacteristic(List<Node> nodes){
		ArrayList<AllowedTermAIMTemplate> result = new ArrayList<AllowedTermAIMTemplate>();
		for (Node at: nodes){
			result.add(new AllowedTermAIMTemplate(at.selectValue("@codeMeaning"), at.selectValue("@codeValue")));
		}
		return result;
	}

	static ImagingObservationAIMTemplate parseImagingObservation(Node imagingObservation){
		// we had a problem with null pointer exception in here
		if (imagingObservation == null)
			return null;
		ImagingObservationAIMTemplate result = new ImagingObservationAIMTemplate();
		ArrayList<ImagingObservationCharacteristicAIMTemplate> imagingObservationCharacteristicAIMTemplates = new ArrayList<ImagingObservationCharacteristicAIMTemplate>();
		for (Node i : imagingObservation.selectNodes("aim:ImagingObservationCharacteristic") ){
			imagingObservationCharacteristicAIMTemplates.add(
					new ImagingObservationCharacteristicAIMTemplate(
							Integer.parseInt(i.selectValue("@itemNumber")),
							Integer.parseInt(i.selectValue("@minCardinality")),
							Integer.parseInt(i.selectValue("@maxCardinality")),
							i.selectValue("@label"),
							i.selectValue("@explanatoryText"),
							i.selectValue("@annotatorConfidence").equalsIgnoreCase("true"), 
							i.selectValue("@shouldDisplay").equalsIgnoreCase("true"), 
						    parseAllowedTermComponentCharacteristic(i.selectNodes("aim:AllowedTerm"))));
			
		}
		result.setImagingObservationCharacteristicAIMTemplates(imagingObservationCharacteristicAIMTemplates);
		result.setAnnotatorConfidence(imagingObservation.selectValue("@annotatorConfidence").equalsIgnoreCase("true"));
		return result;		
	}
	
	static QuestionTypeAIMTemplate parseQuestionType(Node v){
		// we had a problem with null pointer exception in here
		if( v == null)
			return null;
		return new QuestionTypeAIMTemplate(
				v.selectValue("@codeMeaning"),
				v.selectValue("@codeValue"),
				v.selectValue("@codingSchemeDesignator"));
	}
	
	static CalculationTypeAIMTemplate parseCalculation(Node ca){
		// we had a problem with null pointer exception in here
		if( ca == null)
			return null;
		Node c = ca.selectNodes("aim:CalculationType").get(0);
		return new CalculationTypeAIMTemplate(
				c.selectValue("@codeMeaning"),
				c.selectValue("@codeValue"),
				c.selectValue("@codingSchemeDesignator"),
				parseValidTerms(c.selectNodes("aim:ValidTerm")),
				parseAlgorithmType(c.selectNodes("aim:AlgorithmType")));
	}

	static ArrayList<AllowedTermAIMTemplate> parseValidTerms(List<Node> nodes){
		ArrayList<AllowedTermAIMTemplate> result = new ArrayList<AllowedTermAIMTemplate>();
		for (Node vt: nodes){
			result.add(new AllowedTermAIMTemplate(
					vt.selectValue("@codeMeaning"),
					vt.selectValue("@codeValue")));
		}
		return result;
	}
	
	static AlgorithmTypeAIMTemplate parseAlgorithmType(List<Node> nodes){
		if(nodes.isEmpty())
			return null;
		Node aa = nodes.get(0);
		return new AlgorithmTypeAIMTemplate(
				aa.selectValue("@codeMeaning"),
				aa.selectValue("@codingSchemeDesignator"),
				aa.selectValue("@codeValue"),
				aa.selectValue("@description"),
				aa.selectValue("@algorithmName"),
				aa.selectValue("@algorithmVersion"),
				aa.selectValue("@uniqueIdentifier"));
	}
	
//	public static void test(String text) {
////		text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <TemplateContainer> <Template t1=\"jjj\">  </Template> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> <div t1=\"j\">  </div> </TemplateContainer>";
//
////		System.out.println(text);
//		
//		String namespace= "xmlns:aim=\"gme://caCORE.caCORE/3.2/edu.northwestern.radiology.AIMTemplate\" "
//                        + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
//		Document document = new XmlParser().parse(text, namespace);
////		Element root = document.getRoot();
//		List<Comment> comments = document.findByType(NodeType.ELEMENT);
//		List<Node> products = document.selectNodes("//aim:Template");
//		
//		System.out.println(parseTemplateAIMTemplate(document, "LIDC CT"));
//		
//		System.out.println(products.size());
////		System.out.println(products);
//		System.out.println(comments.size());
//	//	System.out.println(comments);
//	}
}
